package com.h3c.ptability.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class PmJwtUtil {

    private static final String JWT_PAYLOAD_USER_KEY = "user";

    /**
     * 获取公钥
     *
     * @param bytes 公钥的字节形式
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(byte[] bytes) throws Exception {
        bytes = Base64.getDecoder().decode(bytes);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(spec);
    }

    /**
     * 公钥解析token
     * @param token
     * @param publicKey
     * @return
     */
    public static Claims getClaims(String token, String publicKey) {
        try {
            PublicKey publicKeyObj = getPublicKey(publicKey.getBytes());
            Jws<Claims> claimsJws = parserToken(token, publicKeyObj);
            return claimsJws.getBody();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取密钥
     *
     * @param bytes 私钥的字节形式
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes = Base64.getDecoder().decode(bytes);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(spec);
    }

    /**
     * 私钥加密token
     *
     * @param domainAccount  域账号
     * @param privateKey     私钥
     * @param addMileSeconds 过期时间，单位毫秒
     * @return JWT
     */
    public static String generateTokenExpire(String domainAccount, String privateKey, long addMileSeconds, Map<String,Object> claims) throws Exception {
        PrivateKey privateKeyObj = getPrivateKey(privateKey.getBytes());
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        return Jwts.builder()
                .setClaims(claims)
                .setId(domainAccount)
                .setIssuedAt(now)
                .setExpiration(new Date(nowMillis + addMileSeconds))
                .signWith(SignatureAlgorithm.RS256, privateKeyObj)
                .compact();
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥
     * @return Jws<Claims>
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

//    private static String createJTI() {
//        return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));
//    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     */
    public static String getUserIdFromToken(String token, String publicKey) {
        try {
            PublicKey publicKeyObj = getPublicKey(publicKey.getBytes());
            Jws<Claims> claimsJws = parserToken(token, publicKeyObj);
            Claims body = claimsJws.getBody();
            return body.getId();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
